using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Complaint.Common;
using Complaint.Models;
using Complaint.Models.Dtos;
using Complaint.Models.Dtos.Enums;
using Complaint.Services;
using MvcContrib.Pagination;

namespace Complaint.Controllers
{
    [HandleError]
    public class OrganisationController : BaseController
    {
        //
        // GET: /Organisation/

        public ActionResult Index(int? page)
        {
            using (new UnitOfWorkScope(false))
            {
                var model = new OrganisationModel();
                var totalCount = model.Retrieve().Count;
                var orgs = model.Retrieve(page ?? 1, PageSize).AsEnumerable();
                orgs = new CustomPagination<Organisation>(orgs, page ?? 1, PageSize, totalCount);

                if (!Request.IsAjaxRequest())
                    return View(orgs);

                return PartialView("Grid", orgs);
            }
        }

        //
        // GET: /Organisation/Details/5

        public ActionResult Details(int id)
        {
            using (new UnitOfWorkScope(false))
            {
                var model = new OrganisationModel();
                var org = model.FindById(id, LoadOrganisation.Category | LoadOrganisation.Alias | LoadOrganisation.Contact);
                return View(org);
            }
        }

        //
        // GET: /Organisation/Create

        public ActionResult Create()
        {
            var organisation = new Organisation();
            return View(organisation);

            //return View(
            //    new ViewModelWithDataList<Organisation, Category, CategoryModel>(
            //        organisation, "CategoryID", "Title"
            //        ));
        }

        //
        // POST: /Organisation/Create

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(Organisation organisation)
        {
            try
            {
                using (new UnitOfWorkScope(true))
                {
                    var model = new OrganisationModel();
                    var categoryModel = new CategoryModel();

                    var serializer = new JavaScriptSerializer();
                    var categoryVals = Request.Form["categoryIDs"];
                    var aliasVals = Request.Form["aliases"];
                    var contactVals = Request.Form["contactJson"];
                    var categoryIDs = serializer.Deserialize<int[]>(categoryVals);
                    var aliases = serializer.Deserialize<string[]>(aliasVals);
                    var contacts = serializer.Deserialize<Contact[]>(contactVals);

                    foreach (var i in categoryIDs)
                    {
                        var category = categoryModel.FindById(i);
                        if (category != null)
                            organisation.Category.Add(category);
                    }

                    foreach (var a in aliases)
                    {
                        var alias = new OrganisationAlias {Alias = a};
                        organisation.OrganisationAlias.Add(alias);
                    }

                    foreach (var c in contacts)
                    {
                        organisation.Contact.Add(c);
                    }

                    model.Create(organisation);
                    return View("Confirmation", organisation);
                }

            }
            catch (ComplaintDataException e)
            {
                foreach (var error in e.DataValidationErrors)
                {
                    ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                    //if (ModelState[error.PropertyName].Value == null)
                    //{
                    //    ModelState[error.PropertyName].Value =
                    //        new ValueProviderResult(
                    //            null,
                    //            null,
                    //            CultureInfo.CurrentCulture);
                    //}
                }

                return View(organisation);
            }
        }

        //
        // GET: /Organisation/Edit/5
        [Authorize(Roles = "Admin")]
        public ActionResult Edit(int id)
        {
            using (new UnitOfWorkScope(false))
            {
                var model = new OrganisationModel();
                var organisation = model.FindById(id, LoadOrganisation.Category | LoadOrganisation.Alias | LoadOrganisation.Contact);
                return View(organisation);
            }
        }

        //
        // POST: /Organisation/Edit/5

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection formValues)
        {
            Organisation organisation;
            try
            {
                using (new UnitOfWorkScope(true))
                {
                    var model = new OrganisationModel();
                    var categoryModel = new CategoryModel();

                    var serializer = new JavaScriptSerializer();
                    var categoryIDs = serializer.Deserialize<int[]>(Request.Form["categoryIDs"]);
                    var aliases = serializer.Deserialize<string[]>(Request.Form["aliases"]);
                    var categories = new List<Category>();

                    organisation = model.FindById(id, LoadOrganisation.Category | LoadOrganisation.Alias | LoadOrganisation.Contact);
                    UpdateModel(organisation);

                    //populate the selected category list
                    foreach (var i in categoryIDs)
                    {
                        var category = categoryModel.FindById(i);
                        if (category != null)
                        {
                            categories.Add(category);
                        }
                    }

                    OrganisationHelper.SyncCategories(organisation, categories);
                    OrganisationHelper.SyncAlias(organisation, aliases);

                    model.Update(organisation);
                    return RedirectToAction("Details", new {id});
                }
            }
            catch (ComplaintDataException e)
            {
                foreach (var error in e.DataValidationErrors)
                {
                    ModelState.AddModelError(error.PropertyName ?? "", error.ErrorMessage);
                }
                var model = new OrganisationModel();
                organisation = model.FindById(id, LoadOrganisation.Category | LoadOrganisation.Alias | LoadOrganisation.Contact);
                return View(organisation);
            }
        }

        public ActionResult AddContact(int id)
        {
            var contact = new Contact();
            ViewData["OrganisationID"] = id;
            var titles = ConfigHelper
                .GetConfigValue("Titles")
                .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            ViewData["Titles"] = new SortedList<string, string>(titles.ToDictionary(s => s));
 
            return PartialView(contact);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult AddContact(int id, string json)
        {
            var contact = new Contact();
            try
            {
                using (new UnitOfWorkScope(true))
                {
                    var model = new OrganisationModel();
                    var organisation = model.FindById(
                        id,
                        LoadOrganisation.Category | LoadOrganisation.Alias | LoadOrganisation.Contact);
                    contact = contact.FromJson(json);

                    organisation.Contact.Add(contact);
                    model.Update(organisation);
                    return PartialView("ContactList", organisation.Contact.ToList());
                }
            }
            catch (ComplaintDataException e)
            {
                foreach (var error in e.DataValidationErrors)
                {
                    ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                    // if Builtin Model Binding is not used, for every ModelError added, a ModelValue is also needed 
                    if (ModelState[error.PropertyName].Value == null)
                    {
                        ModelState[error.PropertyName].Value = 
                            new ValueProviderResult(
                                ReflectionHelper.GetValue(contact, error.PropertyName).ToString(), 
                                ReflectionHelper.GetValue(contact, error.PropertyName).ToString(), 
                                CultureInfo.CurrentCulture);
                    }
                }
            }
            catch (ApplicationException ae)
            {
                ModelState.AddModelError("_FORM", ae.Message);
            }
            Response.StatusCode = 500;
            ViewData["OrganisationID"] = id;
            return PartialView(contact);
        }

        public ActionResult EditContact(int id)
        {
            using (new UnitOfWorkScope(false))
            {
                var model = new ContactModel();
                var contact = model.FindById(id);
                var titles = ConfigHelper
                                .GetConfigValue("Titles")
                                .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                ViewData["Titles"] = new SortedList<string, string>(titles.ToDictionary(s => s));

                return PartialView("EditContact", contact);
            }
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditContact(int id, string json)
        {
            var o = new Contact().FromJson(json);
            try
            {

                using (new UnitOfWorkScope(true))
                {
                    var model = new ContactModel();
                    var contact = model.FindById(id);
                    o.Copy(ref contact);
                    model.Update(contact);

                    var orgId = (int)contact.OrganisationReference.EntityKey.EntityKeyValues.FirstOrDefault().Value;
                    var contacts = model.FindByOrganisation(orgId);

                    return PartialView("ContactList", contacts);
                }
            }
            catch (ComplaintDataException e)
            {
                foreach (var error in e.DataValidationErrors)
                {
                    ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
                }
                var model = new ContactModel();
                o = model.FindById(id);
                Response.StatusCode = 500;
                return PartialView("EditContact", o);
            }
        }

        public ActionResult DeleteContact(int id, int organisationId)
        {
            try
            {
                using (new UnitOfWorkScope(true))
                {
                    var model = new ContactModel();
                    model.Delete(model.FindById(id));

                    return PartialView("ContactList", model.FindByOrganisation(organisationId));
                }
            }
            catch (ComplaintDataException)
            {
                return Content("Failed to delete due to an error.");
            }
        }

        public ActionResult Search(string keywords, int? page)
        {
            using (new UnitOfWorkScope(false))
            {
                var model = new OrganisationModel();
                var orgs = String.IsNullOrEmpty(keywords)
                     ? model.Retrieve().AsPagination(page ?? 1, PageSize)
                     : model.FindByKeywords(keywords, LoadOrganisation.Alias | LoadOrganisation.Category | LoadOrganisation.Contact)
                            .AsPagination(page ?? 1, PageSize);
                ViewData["Keywords"] = keywords;

                return PartialView("Grid", orgs);
            }
        }

        public ActionResult AddAlias()
        {
            return PartialView("AliasForm");
        }

        //public ActionResult AddCategory(int organisationID, int categoryID)
        //{
        //    using (new UnitOfWorkScope(true))
        //    {
        //        var model = new OrganisationModel();
        //        var organisation = model.FindById(id);
        //        var categoryMode = new CategoryModel();
        //        var category = categoryMode.FindById(categoryID);

        //        if (organisation.Category.Contains(category))
        //        {
        //            organisation.Category.Add(category);
        //            return Json(category);
        //        }
        //        else
        //        {
        //            ModelState.AddModelError("categoryID", "Category is already exist for the organisation.");
        //            return Json(new { CategoryID = 0, Title = "Category is already exist for the organisation." });
        //        }
        //    }
        //}
    }
}
